package com.wtzz.police.base.aop;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.wtzz.police.base.entity.User;
import com.wtzz.police.base.model.log.WebRequestLog;
import com.wtzz.police.base.model.response.ResponseBean;
import com.wtzz.police.base.util.WebTool;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

//@Component
//@Aspect
//@Slf4j
public class WebRequestLogAop {
	
	private ObjectMapper om = new ObjectMapper();
	
	@Around("@annotation(io.swagger.annotations.ApiOperation) && within(com.wtzz.*.controller..*)")
	public Object webLogByApiOperationAbrond(ProceedingJoinPoint joinPoint) throws Throwable {
		MethodSignature ms = (MethodSignature) joinPoint.getSignature();
		ApiOperation apiOperation = ms.getMethod().getAnnotation(ApiOperation.class);
		
		StringBuffer action = new StringBuffer();
		Api api = joinPoint.getTarget().getClass().getAnnotation(Api.class);
		if(api != null) {
			if(api.tags()!=null && api.tags().length>0 && StringUtils.isNotEmpty(api.tags()[0]))
				action.append(api.tags()[0]).append("/");
			else if(StringUtils.isNotEmpty(api.value()))
				action.append(api.value()).append("/");
		}
		
		action.append(apiOperation.value());
		
		WebRequestLog o = new WebRequestLog();
		o.setAction(action.toString());
		o.setIp(WebTool.getRequest().getRemoteAddr());
		o.setUri(WebTool.getRequest().getRequestURI());
		
		
		if(StringUtils.isEmpty(o.getAccount())) {
			User u = WebTool.getCurrentUser();
			if(u!=null) {
				o.setAccount(u.getUsername());
				if(u.getDepartment()!=null) {
					o.setDepartment(u.getDepartment());
				}
			}
		}
		
		Object [] args = joinPoint.getArgs();
		if(args!=null && args.length>0) {
			Map<String,Object> m = new HashMap<>();
			for(int i=0;i<ms.getParameterNames().length;i++)
				if(!existsTypes(args[i]))
					m.put(ms.getParameterNames()[i], args[i]);
			o.setParams(om.writeValueAsString(m));
		}
		
		Object obj = joinPoint.proceed();
		
		if(obj!=null && obj instanceof ResponseBean<?>) {
			o.setResponse(om.writeValueAsString(obj));
		}
//		log.debug(om.writeValueAsString(o));
		return obj;
	}
	
	
	private Set<Class<?>> types = new HashSet<>();
	{
		types.add(MultipartFile.class);
		types.add(HttpServletRequest.class);
		types.add(HttpServletResponse.class);
	}
	
	
	private boolean existsTypes(Object o) {
		if(o == null)return false;
		return types.parallelStream().anyMatch(t->t.isAssignableFrom(o.getClass()));
	}
	

	public void webLogAfterThrowing() {
		
	}
}